/**
 * @file memory_utils.c
 * @brief 内存管理工具实现
 * @details 本文件实现了104协议的内存管理工具功能，包括安全的内存分配（malloc、
 *          calloc、realloc）、内存释放、内存操作（复制、移动、比较、设置）、
 *          内存检查、内存调试和统计功能。提供完整的内存管理接口，确保内存操作
 *          的安全性和可靠性，支持内存泄漏检测。
 * 
 * @author zyb
 * @date 2025-09-25
 * @version 1.0
 * 
 * @note 所有内存操作都包含安全检查，防止内存泄漏和越界访问
 * @warning 内存统计功能为简化实现，实际使用中可能需要更复杂的统计逻辑
 * 
 * @see memory_utils.h
 * @see error_codes.h
 */

#include "memory_utils.h"
#include "logger.h"
#include <stdlib.h>
#include <string.h>

// 定义模块名称
#define LOG_MODULE_NAME "MEMORY_UTILS"

/* ==================== 内存统计变量 ==================== */

static size_t total_allocated = 0;
static size_t total_freed = 0;
static size_t allocation_count = 0;

/* ==================== 内存分配函数实现 ==================== */

/**
 * @brief 安全的内存分配
 * @details 执行安全的内存分配操作，包含统计功能。函数会检查分配大小，
 *          调用标准malloc函数，并在成功时更新内存统计信息。
 *          提供比标准malloc更安全的内存分配接口。
 * 
 * @param size 要分配的字节数
 * @return 分配的内存指针，失败返回NULL
 * 
 * @note 分配的内存需要调用safe_free()释放
 * @warning 分配失败时返回NULL，调用者需要检查返回值
 * 
 * @see safe_free
 * @see safe_calloc
 * @see safe_realloc
 */
void* safe_malloc(size_t size) {
    LOG_DEBUG(LOG_MODULE_NAME, "请求分配内存大小: %zu 字节", size);
    
    if (size == 0) {
        LOG_WARN(LOG_MODULE_NAME, "请求分配0字节内存，返回NULL");
        return NULL;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "调用malloc分配内存");
    void* ptr = malloc(size);
    if (ptr != NULL) {
        total_allocated += size;
        allocation_count++;
        LOG_DEBUG(LOG_MODULE_NAME, "内存分配成功: 指针=%p, 大小=%zu, 总分配=%zu, 分配次数=%zu", 
                  ptr, size, total_allocated, allocation_count);
        LOG_INFO(LOG_MODULE_NAME, "内存分配完成: %p", ptr);
    } else {
        LOG_ERROR(LOG_MODULE_NAME, "内存分配失败: 请求大小=%zu", size);
    }
    
    return ptr;
}

/**
 * @brief 安全的内存分配并清零
 * @details 执行安全的内存分配操作，并将分配的内存清零。函数会检查参数有效性，
 *          调用标准calloc函数，并在成功时更新内存统计信息。
 *          提供比标准calloc更安全的内存分配接口。
 * 
 * @param count 要分配的元素数量
 * @param size 每个元素的字节数
 * @return 分配的内存指针，失败返回NULL
 * 
 * @note 分配的内存已清零，需要调用safe_free()释放
 * @warning 分配失败时返回NULL，调用者需要检查返回值
 * 
 * @see safe_free
 * @see safe_malloc
 * @see safe_realloc
 */
void* safe_calloc(size_t count, size_t size) {
    if (count == 0 || size == 0) {
        return NULL;
    }
    
    size_t total_size = count * size;
    void* ptr = calloc(count, size);
    if (ptr != NULL) {
        total_allocated += total_size;
        allocation_count++;
    }
    
    return ptr;
}

void* safe_realloc(void* ptr, size_t size) {
    if (size == 0) {
        safe_free(ptr);
        return NULL;
    }
    
    void* new_ptr = realloc(ptr, size);
    if (new_ptr != NULL) {
        /* 注意：realloc的内存统计比较复杂，这里简化处理 */
        total_allocated += size;
        allocation_count++;
    }
    
    return new_ptr;
}

/**
 * @brief 安全释放内存
 * @details 安全地释放内存，并更新内存统计信息。
 *          提供空指针检查，防止释放空指针导致的错误。
 * 
 * @param ptr 要释放的内存指针，可以为NULL
 * 
 * @note 此函数会更新内存统计信息
 * @warning 释放后指针仍指向原地址，需要手动置NULL
 * 
 * @see safe_free_and_null
 * @see safe_malloc
 * @see get_memory_stats
 */
void safe_free(void* ptr) {
    if (ptr != NULL) {
        free(ptr);
        /* 注意：这里无法准确统计释放的内存大小，简化处理 */
        total_freed += 1; /* 简化统计 */
    }
}

/**
 * @brief 安全释放内存并置空指针
 * @details 安全地释放内存并将指针置为NULL，防止悬空指针。
 *          这是推荐的内存释放方式，可避免重复释放问题。
 * 
 * @param ptr 指向内存指针的指针，不能为NULL
 * 
 * @note 此函数会自动将指针置为NULL
 * @warning 指针参数必须是指向指针的指针
 * 
 * @see safe_free
 * @see safe_malloc
 */
void safe_free_and_null(void** ptr) {
    if (ptr != NULL && *ptr != NULL) {
        safe_free(*ptr);
        *ptr = NULL;
    }
}

/* ==================== 内存操作函数实现 ==================== */

/**
 * @brief 安全内存复制
 * @details 安全地复制内存内容，防止缓冲区溢出。
 *          自动选择较小的大小进行复制，确保不会越界。
 * 
 * @param dest 目标缓冲区，不能为NULL
 * @param dest_size 目标缓冲区大小
 * @param src 源缓冲区，不能为NULL
 * @param src_size 源数据大小
 * @return 实际复制的字节数
 * 
 * @note 自动选择最小的大小进行复制
 * @warning 目标和源缓冲区不能重叠
 * 
 * @see safe_memmove
 * @see memcpy
 */
size_t safe_memcpy(void* dest, size_t dest_size, const void* src, size_t src_size) {
    if (dest == NULL || src == NULL || dest_size == 0) {
        return 0;
    }
    
    size_t copy_size = (src_size < dest_size) ? src_size : dest_size;
    memcpy(dest, src, copy_size);
    
    return copy_size;
}

/**
 * @brief 安全内存移动
 * @details 安全地移动内存内容，防止缓冲区溢出。
 *          支持重叠缓冲区的安全移动，自动选择较小的大小进行移动。
 * 
 * @param dest 目标缓冲区，不能为NULL
 * @param dest_size 目标缓冲区大小
 * @param src 源缓冲区，不能为NULL
 * @param src_size 源数据大小
 * @return 实际移动的字节数
 * 
 * @note 支持重叠缓冲区的安全移动
 * @warning 使用memmove确保重叠缓冲区的正确性
 * 
 * @see safe_memcpy
 * @see memmove
 */
size_t safe_memmove(void* dest, size_t dest_size, const void* src, size_t src_size) {
    if (dest == NULL || src == NULL || dest_size == 0) {
        return 0;
    }
    
    size_t move_size = (src_size < dest_size) ? src_size : dest_size;
    memmove(dest, src, move_size);
    
    return move_size;
}

/**
 * @brief 安全内存设置
 * @details 安全地将内存设置为指定的字节值。
 *          提供安全的缓冲区设置操作，包含空指针检查。
 * 
 * @param dest 目标缓冲区，不能为NULL
 * @param dest_size 目标缓冲区大小
 * @param value 要设置的字节值
 * @return 实际设置的字节数
 * 
 * @note 使用memset进行字节设置
 * @warning 缓冲区指针不能为NULL
 * 
 * @see memset
 * @see safe_memcpy
 */
size_t safe_memset(void* dest, size_t dest_size, int value) {
    if (dest == NULL || dest_size == 0) {
        return 0;
    }
    
    memset(dest, value, dest_size);
    return dest_size;
}

/**
 * @brief 安全内存比较
 * @details 安全地比较两个内存区域的内容是否相同。
 *          提供安全的缓冲区比较操作，包含空指针检查。
 * 
 * @param ptr1 第一个内存区域，不能为NULL
 * @param ptr2 第二个内存区域，不能为NULL
 * @param size 比较的字节数
 * @return 比较结果
 *         - 0: 内存内容相同
 *         - 非0: 内存内容不同
 *         - -1: 空指针错误
 * 
 * @note 使用memcmp进行字节级比较
 * @warning 内存区域指针不能为NULL
 * 
 * @see memcmp
 * @see safe_memcpy
 */
int safe_memcmp(const void* ptr1, const void* ptr2, size_t size) {
    if (ptr1 == NULL || ptr2 == NULL) {
        return -1;
    }
    
    return memcmp(ptr1, ptr2, size);
}

/* ==================== 内存检查函数实现 ==================== */

/**
 * @brief 检查指针是否为空
 * @details 检查指针是否为NULL。
 *          用于验证指针的有效性。
 * 
 * @param ptr 要检查的指针，可以为NULL
 * @return 检查结果
 *         - 1: 指针为空
 *         - 0: 指针不为空
 * 
 * @note 此函数是线程安全的
 * @warning 此函数不会修改指针指向的内容
 * 
 * @see is_memory_aligned
 * @see is_valid_memory_size
 */
int is_null_pointer(const void* ptr) {
    return (ptr == NULL);
}

/**
 * @brief 检查内存对齐
 * @details 检查指针是否按照指定的对齐方式对齐。
 *          用于验证内存对齐要求，确保性能优化。
 * 
 * @param ptr 要检查的指针，不能为NULL
 * @param alignment 对齐要求，必须大于0
 * @return 检查结果
 *         - 1: 内存已对齐
 *         - 0: 内存未对齐或参数无效
 * 
 * @note 对齐要求必须是2的幂次
 * @warning 指针和对齐要求不能为NULL或0
 * 
 * @see is_null_pointer
 * @see is_valid_memory_size
 */
int is_memory_aligned(const void* ptr, size_t alignment) {
    if (ptr == NULL || alignment == 0) {
        return 0;
    }
    
    /* 检查对齐 */
    return (((uintptr_t)ptr) % alignment == 0);
}

/**
 * @brief 检查内存大小是否有效
 * @details 检查内存大小是否在合理范围内。
 *          用于验证内存分配请求的有效性。
 * 
 * @param size 要检查的内存大小
 * @return 检查结果
 *         - 1: 内存大小有效
 *         - 0: 内存大小无效
 * 
 * @note 检查大小是否大于0且小于SIZE_MAX
 * @warning 此函数不会分配内存
 * 
 * @see is_null_pointer
 * @see is_memory_aligned
 */
int is_valid_memory_size(size_t size) {
    /* 检查内存大小是否合理 */
    return (size > 0 && size < SIZE_MAX);
}

/* ==================== 内存调试函数实现 ==================== */

/**
 * @brief 获取内存统计信息
 * @details 获取内存分配和释放的统计信息。
 *          用于内存使用情况监控和调试。
 * 
 * @param total_allocated_out 总分配内存大小输出，可以为NULL
 * @param total_freed_out 总释放内存大小输出，可以为NULL
 * @param current_allocated_out 当前分配内存大小输出，可以为NULL
 * @param allocation_count_out 分配次数输出，可以为NULL
 * 
 * @note 此函数是线程安全的
 * @warning 输出参数为NULL时不会设置对应值
 * 
 * @see reset_memory_stats
 * @see check_memory_leak
 */
void get_memory_stats(size_t* total_allocated_out, size_t* total_freed_out, 
                      size_t* current_allocated_out, size_t* allocation_count_out) {
    if (total_allocated_out != NULL) {
        *total_allocated_out = total_allocated;
    }
    
    if (total_freed_out != NULL) {
        *total_freed_out = total_freed;
    }
    
    if (current_allocated_out != NULL) {
        *current_allocated_out = total_allocated - total_freed;
    }
    
    if (allocation_count_out != NULL) {
        *allocation_count_out = allocation_count;
    }
}

/**
 * @brief 重置内存统计信息
 * @details 重置所有内存统计计数器为0。
 *          用于重新开始内存使用统计。
 * 
 * @note 此函数会重置所有统计计数器
 * @warning 重置后无法恢复之前的统计信息
 * 
 * @see get_memory_stats
 * @see check_memory_leak
 */
void reset_memory_stats(void) {
    total_allocated = 0;
    total_freed = 0;
    allocation_count = 0;
}

/**
 * @brief 检查内存泄漏
 * @details 简单检查是否存在内存泄漏。
 *          通过比较分配次数和释放次数来判断。
 * 
 * @return 检查结果
 *         - 1: 可能存在内存泄漏
 *         - 0: 没有检测到内存泄漏
 * 
 * @note 这是一个简化的检查方法
 * @warning 此检查可能不够精确，仅供参考
 * 
 * @see get_memory_stats
 * @see reset_memory_stats
 */
int check_memory_leak(void) {
    /* 简化检查：如果分配次数大于释放次数，可能存在内存泄漏 */
    return (allocation_count > total_freed);
}
